#include "wordlist.h"

WordList::WordList( wxString& dict, wxSQLite3Database *pDictDb, wxSQLite3Database *pCardDb, wxString& soundFileDir )
: WordDialog( NULL ), BaseList( m_listCtrl, soundFileDir )
{
	m_sSoundDir += wxT("/") + dict;
	
	m_sDictName = dict;
	m_pDictDb = pDictDb;
	m_pCardDb = pCardDb;
	
	m_iWordNum = -1;
	m_lItemIdx = -1;
	
	m_listCtrl->InsertColumn( eWord_Id,    _("Id"),          wxLIST_FORMAT_LEFT, 0 );
	m_listCtrl->InsertColumn( eWord_Word,  _("Word"),        wxLIST_FORMAT_LEFT, 210 );
	m_listCtrl->InsertColumn( eWord_Tran,  _("Translation"), wxLIST_FORMAT_LEFT, 360 );
	
	m_buttonOk->SetFocus();
}

WordList::~WordList()
{
}

void WordList::OnEnterWindow( wxMouseEvent& event )
{
	m_listCtrl->SetFocus();
}

void WordList::Load()
{
	m_iWordNum = FillWordList();
}

long WordList::FillWordList( bool bClear )
{
	// clear list
	if( bClear )
	{
		ClearInfo();
		m_pcListCtrl->DeleteAllItems();
	}
		
	// get words
	wxSQLite3ResultSet cWordSet = m_pDictDb->ExecuteQuery( wxT( "SELECT * FROM " ) + m_sDictName + wxT( " WHERE id > 1 ORDER By word" ) );
	
	long iCount = 0;
	
	while( cWordSet.NextRow() )
	{	
		wxString s[eWord_Cols];
			
		for( int i = 0; i < eWord_Cols; i++ )
			s[i] = cWordSet.GetAsString(i);			
			
		InsertItem( s, eWord_Cols );
		
		iCount++;
	}
		
	cWordSet.Finalize();
		
	return iCount;
}

void WordList::ClearInfo()
{
	m_sWordId.clear();
	m_sFile.Clear();
	m_sWord.Clear();
	m_sTran.Clear();

	SetWord( m_sWord );
	SetTran( m_sTran );
	SetFile( m_sFile );

	m_buttonPlay->Enable( false );
}

void WordList::SetInfo()
{
	m_lItemIdx = m_listCtrl->GetNextItem( -1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED );

	m_sWordId = GetColumnText( eWord_Id );		
	m_sWord   = GetColumnText( eWord_Word );		
	m_sTran   = GetColumnText( eWord_Tran );	

	SetWord( m_sWord );
	SetTran( m_sTran );

	m_sFile = m_sWordId;
	m_sFile = GetFileName( m_sFile );
	SetFile( m_sFile );

	m_buttonPlay->Enable( true );
}

void WordList::OnCancelClick( wxCommandEvent& WXUNUSED( event ) )
{
	if( IsModal() )
		EndModal( wxID_CANCEL );
}

void WordList::OnWordDeselected( wxListEvent& WXUNUSED( event ) )
{	
	if( m_listSelectedItems.size() )
	{
		std::list<long>::iterator it = m_listSelectedItems.begin();
		long idx = *it;
		m_listSelectedItems.erase( it );
		m_listCtrl->DeleteItem( idx );
	}
		
	m_buttonPlay->Enable( false );
	
	// reduce number of selected items
	m_lItemNum--;

	if( m_lItemNum == 1 )
		SetInfo();
	else
		ClearInfo();

	if( m_lItemNum == 0 )
		m_buttonDelete->Enable( false );
}

void WordList::OnWordSelected( wxListEvent& WXUNUSED( event ) )
{	
	m_lItemIdx = -1;
	m_lItemIdx = m_listCtrl->GetNextItem( m_lItemIdx, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED );

	if( m_lItemIdx >= 0 )
	{
		// increase number of selected items
		m_lItemNum++;

		m_buttonDelete->Enable( true );		

		// allow to change info for single selected item
		if( m_lItemNum == 1 )
			SetInfo();
		else
			ClearInfo();
	}
}

void WordList::OnFileClick( wxCommandEvent& WXUNUSED( event ) )
{
	wxFileDialog fileDialog( this, _("Open File"), wxString::FromAscii( getenv( "HOME" ) ), _(""), _("audio files|*.wav;*.ogg|All files (*.*)|*.*"), 0, wxDefaultPosition );
	
	if ( fileDialog.ShowModal() ==  wxID_OK )
  {
		wxString str = fileDialog.GetPath();
		SetFile( str );
  }
}

void WordList::OnOkClick( wxCommandEvent& event )
{
	wxString sWord = GetWord();
	wxString sTran = GetTran();
	wxString sFile = GetFile();
		
	if( ( sWord.empty() || sTran.empty() ) || ( m_sWord == sWord && m_sTran == sTran && m_sFile == sFile ) )
	{
		if( IsModal() )
		{
			EndModal( wxID_OK );
			m_lItemIdx = -1;
		}
		return;
	}
	
	if( m_sWord.empty() && m_sTran.empty() )
	{
		OnInputClick( event );
		return;		
	}
	
	wxString sId = m_pcListCtrl->GetItemText( m_lItemIdx );
	
	// update db entry
	if( ( sWord != m_sWord && sWord.length() && m_sWord.length() ) || ( sTran != m_sTran && sTran.length() && m_sTran.length() ) )
	{		
		wxString sQuery = wxT( "UPDATE " ) + m_sDictName + 
			wxT( " SET word = '") + GetValidString( sWord ) + wxT("', tran = '") + GetValidString( sTran ) + wxT("' WHERE id = ") + sId;
				
		m_pDictDb->ExecuteUpdate( sQuery );
		
		// update item text in the list
		UpdateItem();
	}
	
	if( m_sFile != sFile )
	{
		wxRemoveFile( m_sFile );
		m_sFile.clear();
		
		if( !sFile.empty() )
		{
			wxString ext = sFile.AfterLast( '.' );
			if( ext == GetFile() )
				ext.clear();
			
			m_sFile = m_sSoundDir + wxT("/") + sId + wxT(".") + ext;
			
			wxCopyFile( sFile, m_sFile, true );
		}
		
		SetFile( m_sFile );
	}
}

void WordList::OnDeleteClick( wxCommandEvent& WXUNUSED( event ) )
{
	if( m_lItemIdx < 0 )
		return;
	
	m_lItemIdx = -1;

	while( m_lItemIdx = m_listCtrl->GetNextItem( m_lItemIdx, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED ) >= 0 )
	{
		// store selected items for further deletion
		m_listSelectedItems.push_back( m_lItemIdx );

		wxString sId = m_pcListCtrl->GetItemText( m_lItemIdx );

		// get last word id from db
		wxSQLite3ResultSet cResultSet = m_pDictDb->ExecuteQuery( wxT( "SELECT MAX(id) AS id FROM " ) + m_sDictName );
		wxString sLastWordId = cResultSet.GetAsString(0);
		cResultSet.Finalize();

		// delete word from dict table
		m_pDictDb->ExecuteUpdate( wxT( "DELETE FROM " ) + m_sDictName + wxT(" WHERE id = ") + sId );
		
		// delete sound file
		wxRemoveFile( m_sFile );
	
		m_iWordNum--;
		
		// exchange word id
		if( sLastWordId != sId )
		{
			m_pDictDb->ExecuteUpdate( wxT("UPDATE ") + m_sDictName + wxT(" SET id = ") + sId + wxT(" WHERE id = ") + sLastWordId );
		
			// update file name
			wxString sLastFileName = GetFileName( sLastWordId );
			if( wxFileExists( sLastFileName ) )
			{
				wxString ext = wxT(".") + sLastFileName.AfterLast( '.' );
				wxRename( sLastFileName, m_sFile.BeforeLast( '.' ) + ext );
			}
		
			// update list item
			m_pcListCtrl->SetItem( m_iWordNum, eWord_Id, sId );
		}
	
		// delete the word from all cards
		cResultSet = m_pCardDb->ExecuteQuery( wxT( "SELECT name FROM sqlite_master T WHERE type='table' AND T.name != 'cards'" ) );

		while( cResultSet.NextRow() )
		{			
			wxString sTableName = cResultSet.GetAsString(0);
		
			m_pCardDb->ExecuteUpdate( wxT( "DELETE FROM ") + sTableName + wxT(" WHERE dicttable = '" ) + m_sDictName + wxT("' AND id = ") + sId );
		
			if( sLastWordId != sId )
				m_pCardDb->ExecuteQuery( wxT( "UPDATE ") + sTableName + wxT(" SET id = " ) + sId + wxT(" WHERE dicttable ='") + m_sDictName + wxT("' AND id = ") + sLastWordId );
		}
	
		cResultSet.Finalize();
	}

	// delete first item in the list, others will be deleted in deselected event
	std::list<long>::iterator it = m_listSelectedItems.begin();
	long idx = *it;
	m_listSelectedItems.erase( it );
	m_listCtrl->DeleteItem( idx );
}

void WordList::OnInputClick( wxCommandEvent& WXUNUSED( event ) )
{
	// try do add new db entry
	if( !GetWord().length() )
	{
		m_textCtrlWord->SetFocus();
	}
	else if( !GetTran().length() )
	{
		m_textCtrlTran->SetFocus();
	}
/*
	else if( !GetFile().length() )
	{
		m_textCtrlFile->SetFocus();
	}
*/
	else
	{
		wxString word = GetWord();
		wxString tran = GetTran();		
				
		// check strings validity for SQL query
		CheckValidity( word );
		CheckValidity( tran );
		
		wxString sQuery = wxT( "INSERT INTO " ) + m_sDictName + 
			wxT( " VALUES (NULL, '") + word + wxT("', '") + tran + wxT("')");
	
		m_pDictDb->ExecuteUpdate( sQuery );
	
		// insert word and get id
		wxSQLite3ResultSet cResultSet = m_pDictDb->ExecuteQuery( wxT("SELECT last_insert_rowid() AS id") );
		
		wxString s[eWord_Cols];
		s[eWord_Word] = GetWord();
		s[eWord_Tran] = GetTran();
		s[eWord_Id] = cResultSet.GetAsString(0);
		
		InsertItem( s, eWord_Cols );
						
		if( !GetFile().empty() )
		{
			wxString ext = GetFile().AfterLast( '.' );
			if( ext == GetFile() )
				ext.clear();
			
			wxString file = m_sSoundDir + wxT("/") + s[eWord_Id] + wxT(".") + ext;
			
			if( wxFileExists( file ) )
			{
				if( wxMessageDialog( NULL, file + _("\nAlready exists\n\nOverwrite?"), _("Info"), wxOK | wxCANCEL | wxICON_INFORMATION ).ShowModal() == wxOK )
				{
					wxCopyFile( GetFile(), file, true );
				}
			}
			else
			{
				wxCopyFile( GetFile(), file, false);
			}
		}
		
		ClearInfo();
		
		m_iWordNum++;
	}	
}

void WordList::OnPlayClick( wxCommandEvent& WXUNUSED( event ) )
{
	PlayFile( m_sFile );
}

void WordList::UpdateItem()
{
	if( m_lItemIdx < 0 )
		return;
		
	m_sWord = GetWord();
	m_sTran = GetTran();
		
	m_pcListCtrl->SetItem( m_lItemIdx, eWord_Word, m_sWord );
	m_pcListCtrl->SetItem( m_lItemIdx, eWord_Tran, m_sTran );
}

void WordList::OnLeftDClick( wxMouseEvent& event ) 
{ 
	if( m_bToggle )
		OnOkClick( ( wxCommandEvent& ) event );
	else
		OnPlayClick( ( wxCommandEvent& ) event ); 
}

void WordList::OnKeyDown( wxKeyEvent& event )
{
	if( event.GetKeyCode() == WXK_ESCAPE )
		OnCancelClick( (wxCommandEvent&) event );
	else
		event.Skip();
}

bool WordList::GetWordInfo( wxString& id, wxString& word, wxString& tran )
{
	m_lItemIdx = m_listCtrl->GetNextItem( m_lItemIdx, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED );

	if( m_lItemIdx < 0 )
		return false;

	id   = GetColumnText( eWord_Id );		
	word = GetColumnText( eWord_Word );		
	tran = GetColumnText( eWord_Tran );

	return true;
}